package utils

import (
	"fmt"
	"sync"
	"sync/atomic"
)

type GoroutineLock struct {
	sync.RWMutex
	GoroutineID int64
	reentryNum  int32
}

func (l *GoroutineLock) LockWithGid(goroutineID int64) {
	if l.GoroutineID == goroutineID {
		atomic.AddInt32(&l.reentryNum, 1)
		return
	}
	l.Lock()
	atomic.StoreInt64(&l.GoroutineID, goroutineID)
	atomic.StoreInt32(&l.reentryNum, 1)
}

func (l *GoroutineLock) UnlockWithGid(goroutineID int64) {
	if atomic.LoadInt64(&l.GoroutineID) != goroutineID {
		panic(fmt.Sprintf("unlock goroutineID not match: curID=%v", l.GoroutineID))
	}

	if l.reentryNum--; l.reentryNum == 0 {
		atomic.StoreInt64(&l.GoroutineID, 0)
		l.Unlock()
	}
}
